<?php
// +----------------------------------------------------------------------
// | 实体服务层
// +----------------------------------------------------------------------
// | 主要服务于实体数据处理
// +----------------------------------------------------------------------
// | 错误编码头 205xxx
// +----------------------------------------------------------------------
namespace common\service;

use common\exception\LogicException;
use common\model\EntityModel;
use common\model\OrderModel;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;
use think\module\Module;
use Throwable;
use Webman\Stomp\Client;

class EntityRelationService
{
    // 单例工具
    use SingletonTrait;

    public function __construct()
    {
    }

    /**
     * 镜头关联资产关卡查询
     * @param int $shotId
     * @return array
     */
    public function shotRelateAssetLevelList(int $shotId)
    {
        $shot = model(EntityModel::class)->where(['id' => $shotId])->find();
        if (empty($shot)) {
            throw new LogicException("shot not found", ErrorCode::ENTITY_NOT_FOUND);
        }
        $shotJson = json_decode($shot['json'], true);
        $assetLevelIdList = [];
        $fields = ['shot_asset', 'shot_level'];
        foreach ($fields as $field) {
            foreach (explode(',', $shotJson[$field]) as $relateId) {
                $relateId = intval($relateId);
                if ($relateId > 0) {
                    $assetLevelIdList[$relateId] = $relateId;
                }
            }
        }
        if (empty($assetLevelIdList)) {
            return [];
        }
        $assetLevelFilter = [
            'module_id' => ['IN', [module_by_code('asset')['id'], module_by_code('level')['id']]],
            'id' => ['IN', implode(',', $assetLevelIdList)],
        ];
        $rows = model(EntityModel::class)
            ->where($assetLevelFilter)
            ->field('id,name,code,initial_episode_code,showings_number,module_id,json')
            ->select();
        foreach ($rows as &$row) {
            $moduleCode = module_by_id($row['module_id'])['code'];
            $row['json'] = json_decode($row['json'] ?? '{}', true);
            foreach ($row['json'] as $k => $v) {
                $row[str_replace_once($moduleCode . '_', '', $k)] = $v;
            }
            unset($row['json']);
        }
        return $rows;
    }

    /**
     * 更新概念资产关联关卡
     * @param $data
     * @param string $moduleCode
     * @param $beRelatedEntity
     * @return array
     * @throws Throwable
     */
    public function updateDesignRelation($data, string $moduleCode, $beRelatedEntity)
    {
        $needSyncRelateData = [];
        // 查询出关联了当前实体的概念
        $oldRelatedLevelDesignList = model(EntityModel::class)
            ->where([
                'module_id' => Module::$moduleDictData['module_index_by_code'][$moduleCode]['id'],
                'tenant_id' => $beRelatedEntity['tenant_id'],
                'project_id' => $beRelatedEntity['project_id'],
            ])
            ->where("FIND_IN_SET( '{$beRelatedEntity['name']}' , JSON_UNQUOTE( JSON_EXTRACT( json,'$.level_relate_asset' ) ) )")
            ->select();
        $newRelatedLevelDesignList = [];
        $wantRelateLevelDesign = $data['related_level'] ?? $data['related_asset'] ?? [];
        if (count($wantRelateLevelDesign) > 0) {
            $newRelatedLevelDesignList = model(EntityModel::class)
                ->where([
                    'id' => ['IN', implode(',', $wantRelateLevelDesign)],
                ])
                ->select();
        }
        model(EntityModel::class)->startTrans();
        try {
            $levelNameList = [];
            if (count($oldRelatedLevelDesignList) === 0) {
                // 如果关联的关卡为空 那么直接关联新的
                if (count($wantRelateLevelDesign) > 0) {
                    foreach ($newRelatedLevelDesignList as $newRelatedLevelDesign) {
                        $jsonFields = json_decode($newRelatedLevelDesign['json'], true);
                        $relatedList = explode(',', $jsonFields['level_relate_asset'] ?? "");
                        $relatedList[] = $beRelatedEntity['name'];
                        $relatedStr = implode(',', array_unique($relatedList));
                        model(EntityModel::class)->execute("UPDATE entity SET json = json_set(IFNULL(json,'{}'),'$.level_relate_asset','{$relatedStr}') WHERE id = {$newRelatedLevelDesign['id']}");
                        $needSyncRelateData[] = $newRelatedLevelDesign['id'];
                        $levelNameList[] = $newRelatedLevelDesign['name'];
                    }
                }
            } else {
                // 如果本次操作之前关联的关卡不为空 那么需要对比出 需要移除关联和需要添加关联的概念 进行更新
                $newRelatedLevelDesignList = array_column($newRelatedLevelDesignList, null, 'id');
                $oldRelatedLevelDesignList = array_column($oldRelatedLevelDesignList, null, 'id');
                $oldIdList = array_keys($oldRelatedLevelDesignList);
                $newIdList = array_keys($newRelatedLevelDesignList);
                $needRemovedList = array_diff($oldIdList, $newIdList);
                $needAddedList = array_diff($newIdList, $oldIdList);
                $needKeepList = array_intersect($newIdList, $oldIdList);
                // 需要保留的数据
                foreach ($needKeepList as $keepItemId) {
                    if (isset($newRelatedLevelDesignList[$keepItemId])) {
                        $levelNameList[] = $newRelatedLevelDesignList[$keepItemId]['name'];
                    }
                }
                if (count($needAddedList) > 0) {
                    foreach ($needAddedList as $needAddedId) {
                        $entity = $newRelatedLevelDesignList[$needAddedId] ?? null;
                        if (empty($entity)) {
                            continue;
                        }
                        $jsonFields = json_decode($entity['json'], true);
                        $relatedList = explode(',', $jsonFields['level_relate_asset'] ?? "");
                        $relatedList[] = $beRelatedEntity['name'];
                        $relatedStr = implode(',', array_unique($relatedList));
                        model(EntityModel::class)->execute("UPDATE entity SET json = json_set(IFNULL(json,'{}'),'$.level_relate_asset','{$relatedStr}') WHERE id = {$entity['id']}");
                        $needSyncRelateData[] = $entity['id'];
                        $levelNameList[] = $entity['name'];
                    }
                }
                if (count($needRemovedList)) {
                    foreach ($needRemovedList as $needRemovedId) {
                        $entity = $oldRelatedLevelDesignList[$needRemovedId] ?? null;
                        if (empty($entity)) {
                            continue;
                        }
                        $jsonFields = json_decode($entity['json'], true);
                        $relatedList = explode(',', $jsonFields['level_relate_asset'] ?? "");
                        $relatedList = array_filter($relatedList, function ($item) use ($beRelatedEntity) {
                            return $item !== $beRelatedEntity['name'];
                        });
                        $relatedStr = implode(',', array_unique($relatedList));
                        model(EntityModel::class)->execute("UPDATE entity SET json = json_set(IFNULL(json,'{}'),'$.level_relate_asset','{$relatedStr}') WHERE id = {$entity['id']}");
                        $needSyncRelateData[] = $entity['id'];
                    }
                }
            }
            $levelNameStr = implode(',', $levelNameList);
            model(EntityModel::class)->execute("UPDATE entity set json = json_set(IFNULL(json,'{}'),'$.design_relate_level','{$levelNameStr}') where id = {$beRelatedEntity['id']}");
            model(EntityModel::class)->commit();
        } catch (Throwable $e) {
            model(EntityModel::class)->rollback();
            throw $e;
        }
        return $needSyncRelateData;
    }

    /**
     * 处理关卡关联
     *
     * @param array $data
     * @param string $moduleCode
     * @param array $beRelatedEntity
     * @return array
     */
    public function handleLevelRelation($data, string $moduleCode, $beRelatedEntity)
    {
        $needSyncRelateData = [$beRelatedEntity['id']];
        $oldRelatedLevelAssetList = [];
        if (!empty($entityJson['level_relate_asset'])) {
            $oldRelatedLevelAssetList = model(EntityModel::class)
                ->where([
                    'module_id' => Module::$moduleDictData['module_index_by_code'][$moduleCode]['id'],
                    'tenant_id' => $beRelatedEntity['tenant_id'],
                    'project_id' => $beRelatedEntity['project_id'],
                    'name' => ['IN', array_filter(explode(',', $beRelatedEntity['json']['level_relate_asset']))],
                ])
                ->select();
        }
        $newRelatedLevelAssetList = [];
        $wantRelateLevelAsset = $data['related_level'] ?? $data['related_asset'] ?? [];
        if (count($wantRelateLevelAsset) > 0) {
            $newRelatedLevelAssetList = model(EntityModel::class)
                ->where([
                    'id' => ['IN', implode(',', $wantRelateLevelAsset)],
                ])
                ->select();
        }
        model(EntityModel::class)->startTrans();
        try {
            $assetNameList = [];
            if (count($oldRelatedLevelAssetList) === 0) {
                // 如果关联的资产为空 那么直接关联新的
                if (count($wantRelateLevelAsset) > 0) {
                    foreach ($newRelatedLevelAssetList as $newRelatedLevelDesign) {
                        $jsonFields = json_decode($newRelatedLevelDesign['json'], true);
                        $relatedList = explode(',', $jsonFields['design_relate_level'] ?? "");
                        $relatedList[] = $beRelatedEntity['name'];
                        $relatedStr = implode(',', array_filter(array_unique($relatedList)));
                        model(EntityModel::class)->execute("UPDATE entity SET json = json_set(IFNULL(json,'{}'),'$.design_relate_level','{$relatedStr}') WHERE id = {$newRelatedLevelDesign['id']}");
                        $assetNameList[] = $newRelatedLevelDesign['name'];
                    }
                }
            } else {
                $newRelatedLevelAssetList = array_column($newRelatedLevelAssetList, null, 'id');
                $oldRelatedLevelAssetList = array_column($oldRelatedLevelAssetList, null, 'id');
                $oldIdList = array_keys($oldRelatedLevelAssetList);
                $newIdList = array_keys($newRelatedLevelAssetList);
                $needRemovedList = array_diff($oldIdList, $newIdList);
                $needAddedList = array_diff($newIdList, $oldIdList);
                $needKeepList = array_intersect($newIdList, $oldIdList);
                // 需要保留的数据
                foreach ($needKeepList as $keepItemId) {
                    $assetNameList[] = $newRelatedLevelAssetList[$keepItemId]['name'];
                }
                if (count($needAddedList) > 0) {
                    foreach ($needAddedList as $needAddedId) {
                        $entity = $newRelatedLevelAssetList[$needAddedId] ?? null;
                        if (empty($entity)) {
                            continue;
                        }
                        $jsonFields = json_decode($entity['json'], true);
                        $relatedList = explode(',', $jsonFields['design_relate_level'] ?? "");
                        $relatedList[] = $beRelatedEntity['name'];
                        $relatedStr = implode(',', array_unique($relatedList));
                        model(EntityModel::class)->execute("UPDATE entity SET json = json_set(IFNULL(json,'{}'),'$.design_relate_level','{$relatedStr}') WHERE id = {$entity['id']}");
                        $assetNameList[] = $entity['name'];
                    }
                }
                if (count($needRemovedList)) {
                    foreach ($needRemovedList as $needRemovedId) {
                        $entity = $oldRelatedLevelAssetList[$needRemovedId] ?? null;
                        if (empty($entity)) {
                            continue;
                        }
                        $jsonFields = json_decode($entity['json'], true);
                        $relatedList = explode(',', $jsonFields['design_relate_level'] ?? "");
                        $relatedList = array_filter($relatedList, function ($item) use ($beRelatedEntity) {
                            return $item !== $beRelatedEntity['name'];
                        });
                        $relatedStr = implode(',', array_unique($relatedList));
                        model(EntityModel::class)->execute("UPDATE entity SET json = json_set(IFNULL(json,'{}'),'$.design_relate_level','{$relatedStr}') WHERE id = {$entity['id']}");
                    }
                }
            }
            $levelNameStr = implode(',', $assetNameList);
            model(EntityModel::class)->execute("UPDATE entity set json = json_set(IFNULL(json,'{}'),'$.level_relate_asset','{$levelNameStr}') where id = {$beRelatedEntity['id']}");
            model(EntityModel::class)->commit();
        } catch (Throwable $e) {
            model(EntityModel::class)->rollback();
            throw $e;
        }
        return $needSyncRelateData;
    }

    /**
     * 处理动作关联
     *
     * @param array $data
     * @param string $moduleCode
     * @param array $beRelatedEntity
     * @return array
     */
    public function handleActionRelation($data, string $moduleCode, $beRelatedEntity)
    {
        $needSyncRelateData = [$beRelatedEntity['id']];
        $wantRelateAsset = $data['related_asset'] ?? [];
        $wantRelateAssetNameList = [];
        if (!empty($wantRelateAsset)) {
            $wantRelateAssetNameList = model(EntityModel::class)->where(['id' => ['IN', $wantRelateAsset]])->field('name')->column('name');
        }
        $assetNameStr = implode(',', $wantRelateAssetNameList);
        model(EntityModel::class)->execute("UPDATE entity set json = json_set(IFNULL(json,'{}'),'$.level_relate_asset','{$assetNameStr}') where id = {$beRelatedEntity['id']}");
        return $needSyncRelateData;
    }

    /**
     * 处理特效关联
     *
     * @param array $data
     * @param string $moduleCode
     * @param array $beRelatedEntity
     * @return array
     */
    public function handleSpecialEffectsRelation($data, string $moduleCode, $beRelatedEntity)
    {
        $needSyncRelateData = [$beRelatedEntity['id']];
        $assetNameStr = null;
        if (isset($data['related_asset'])) {
            $wantRelateAsset = $data['related_asset'];
            $wantRelateAssetNameList = [];
            if (!empty($wantRelateAsset)) {
                $wantRelateAssetNameList = model(EntityModel::class)->where(['id' => ['IN', $wantRelateAsset]])->field('name')->column('name');
            }
            $assetNameStr = implode(',', $wantRelateAssetNameList);
        }
        $levelNameStr = null;
        if (isset($data['related_level'])) {
            $wantRelateLevel = $data['related_level'];
            $wantRelateLevelNameList = [];
            if (!empty($wantRelateLevel)) {
                $wantRelateLevelNameList = model(EntityModel::class)->where(['id' => ['IN', $wantRelateLevel]])->field('name')->column('name');
            }
            $levelNameStr = implode(',', $wantRelateLevelNameList);
        }
        $updateJsonSql = '';
        if (!is_null($assetNameStr)) {
            $updateJsonSql .= ",'$.level_relate_asset','{$assetNameStr}'";
        }
        if (!is_null($levelNameStr)) {
            $updateJsonSql .= ",'$.design_relate_level','{$levelNameStr}'";
        }
        $updateJsonSql = ltrim($updateJsonSql, ',');
        if (!empty($updateJsonSql)) {
            model(EntityModel::class)->execute("UPDATE entity set json = json_set(IFNULL(json,'{}'),{$updateJsonSql}) where id = {$beRelatedEntity['id']}");
        }
        return $needSyncRelateData;
    }

    /**
     * 根据类型更新概念资产关联关卡
     * @param $data
     * @param string $moduleCode
     * @return array|array[]|null
     * @throws Throwable
     */
    public function byTypeUpdateDesignRelation($data, string $moduleCode)
    {
        $beRelatedEntity = model(EntityModel::class)->find($data['id']);
        $needSyncRelateData = [];
        $beRelatedEntity['json'] = json_decode($beRelatedEntity['json'], true);
        if (empty($beRelatedEntity['json']['design_category'])) {
            return null;
        }
        /**
         * 关卡关联场景资产
         * 场景关联关卡
         * 动作关联 角色、道具
         * 特效关联 创意 角色 道具 场景 关卡 动作
         */
        switch ($beRelatedEntity['json']['design_category']) {
            case '场景':
                $needSyncRelateData = $this->updateDesignRelation($data, $moduleCode, $beRelatedEntity);
                break;
            case '关卡':
                $needSyncRelateData = $this->handleLevelRelation($data, $moduleCode, $beRelatedEntity);
                break;
            case '动作':
                $needSyncRelateData = $this->handleActionRelation($data, $moduleCode, $beRelatedEntity);
                break;
            case '特效':
                $needSyncRelateData = $this->handleSpecialEffectsRelation($data, $moduleCode, $beRelatedEntity);
                break;
            case '灯光':
                $needSyncRelateData = $this->handleLightingRelation($data, $moduleCode, $beRelatedEntity);
                break;
        }
        try {
            if ($needSyncRelateData) {
                $chatService = ChatService::getInstance();
                $chat = $chatService->createEntityChat($beRelatedEntity);
                if ($chat) {
                    $message['type'] = 'association_entity_task_message';
                    $message = $chatService->getEntityTaskMessageTemplate($message, request()->getUserId(), $beRelatedEntity);
                    $chatService->pushEntityTaskMessage($message, $chat);
                }
            }
        } catch (Throwable $e) {
            trace(format_exception_info($e), 'ERR');
        }
        $AsyncCallService = AsyncCallService::getInstance();
        // 异步同步关联关系 到关卡和资产
        foreach ($needSyncRelateData as $designId) {
            $AsyncCallService->syncRelationDataAsync($designId, $moduleCode);
            // 同步实体关系后 进行关系写入
            $AsyncCallService->syncRelationDataToEntityRelationShipsAsync($designId);
        }
        return ['relation_changed' => $needSyncRelateData];
    }

    /**
     * 同步关联的数据 (同步关联的资产和关卡到下一个环节实体中)
     * @param $filter
     * @param string $getModuleCode
     * @return array
     * @throws Exception
     */
    public function syncRelationData($filter, string $getModuleCode)
    {
        $res = [];
        $filter['module_id'] = Module::$moduleDictData['module_index_by_code'][$getModuleCode]['id'];
        $entity = model(EntityModel::class)->where($filter)->find();
        /**
         * 分镜同步到镜头和序列
         * 概念同步到资产和关卡
         */
        $entity = array_merge($entity, json_decode($entity['json'], true) ?? []);
        $projectId = $entity['project_id'];
        $sourceAssets = $sourceLevels = $sourceTasks = [];
        $relatedEntities = [];
        $entityChanged = [];
        switch ($getModuleCode) {
            case 'design':
                /**
                 * 查询关联的资产和关卡
                 */
                $sourceAssetField = 'level_relate_asset';
                $sourceLevelField = 'design_relate_level';
                $sourceMedias = explode(',', $entity[$getModuleCode . '_media'] ?? '');
                $downstreamEntity = EntityService::getInstance()->getDownstreamEntity($entity);
                $relatedEntities = [$downstreamEntity];
                $sourceAssetsName = explode(',', $entity[$sourceAssetField] ?? '');
                if (count($relatedEntities) > 0 && count($sourceAssetsName) > 0) {
                    // 资产对象map
                    $assetMap = model(EntityModel::class)
                        ->where([
                            'module_id' => Module::$moduleDictData['module_index_by_code']['asset']['id'],
                            'project_id' => $projectId,
                            'name' => ['IN', $sourceAssetsName],
                        ])
                        ->field('id,name')
                        ->select();
                    $assetMap = array_column($assetMap, 'id', 'name');
                    foreach ($sourceAssetsName as $sourceAssetName) {
                        if (array_key_exists($sourceAssetName, $assetMap)) {
                            $sourceAssets[] = $assetMap[$sourceAssetName];
                        }
                    }
                }
                $sourceLevelsName = explode(',', $entity[$sourceLevelField] ?? '');
                if (count($relatedEntities) > 0 && count($sourceLevelsName)) {
                    // 关卡对象map
                    $levelMap = model(EntityModel::class)
                        ->where([
                            'module_id' => Module::$moduleDictData['module_index_by_code']['level']['id'],
                            'project_id' => $projectId,
                            'name' => ['IN', $sourceLevelsName],
                        ])
                        ->field('id,name')
                        ->select();
                    $levelMap = array_column($levelMap, 'id', 'name');
                    foreach ($sourceLevelsName as $sourceLevelName) {
                        if (array_key_exists($sourceLevelName, $levelMap)) {
                            $sourceLevels[] = $levelMap[$sourceLevelName];
                        }
                    }
                }
                break;
            case 'storyboard':
                /**
                 * 查询分镜对应的序列
                 * 分镜对应的镜头
                 */
                $sourceAssetField = 'storyboard_asset';
                $sourceLevelField = 'storyboard_level';
                $sourceTaskField = 'storyboard_task';
                $sourceMedias = explode(',', $entity[$getModuleCode . '_media'] ?? '');
                $relatedShot = model(EntityModel::class)
                    ->where([
                        'module_id' => Module::$moduleDictData['module_index_by_code']['shot']['id'],
                        'project_id' => $projectId,
                    ])
                    ->where("JSON_UNQUOTE(JSON_EXTRACT(`json`,'$.shot_storyboard')) = {$entity['id']}")
                    ->find();
                if (!empty($relatedShot)) {
                    $relatedEntities = [$relatedShot];
                }
                if (!empty($relatedShot) && $relatedShot['entity_id'] > 0) {
                    // 查询我一集这一序的所有镜头
                    $relatedSequenceShotList = model(EntityModel::class)
                        ->where(['entity_id' => $relatedShot['entity_id']])
                        ->field("id,json->>'$.shot_storyboard' as storyboard_id")
                        ->select();
                    if (count($relatedSequenceShotList) > 0) {
                        // 查询关联的分镜
                        $relatedSequenceShotStoryboardList = model(EntityModel::class)
                            ->where(['id' => ['IN', implode(',', array_column($relatedSequenceShotList, 'storyboard_id'))]])
                            ->field("id,name,code,
                            JSON_UNQUOTE(JSON_EXTRACT(json,'$.storyboard_asset')) as asset,
                            JSON_UNQUOTE(JSON_EXTRACT(json,'$.storyboard_level')) as level,
                            JSON_UNQUOTE(JSON_EXTRACT(json,'$.storyboard_task')) as task,
                            json_unquote(json_extract(json,'$.storyboard_media')) as media")
                            ->select();
                        $sequenceSyncData = [
                            'asset' => [],
                            'level' => [],
                            'media' => [],
                            'task' => [],
                        ];
                        $syncFields = ['asset', 'level', 'media', 'task'];
                        // 组装出最新的关联关系 同步到sequence
                        foreach ($relatedSequenceShotStoryboardList as $storyboard) {
                            $tmp = [];
                            foreach ($syncFields as $field) {
                                $tmp[$field] = $storyboard[$field] ?? '';
                            }
                            foreach ($syncFields as $field) {
                                $tmp[$field] = explode(',', $tmp[$field]);
                                foreach ($tmp[$field] as $item) {
                                    $item = intval($item);
                                    if ($item > 0 && !in_array($item, $sequenceSyncData[$field])) {
                                        $sequenceSyncData[$field][] = $item;
                                    }
                                }
                            }
                        }
                        $entityChanged[] = $relatedShot['entity_id'];
                        $res[] = model(EntityModel::class)->execute("UPDATE `entity` SET `json` = JSON_SET(`json`,
                                '$.sequence_asset','" . implode(',', $sequenceSyncData['asset']) . "',
                                '$.sequence_level','" . implode(',', $sequenceSyncData['level']) . "',
                                '$.sequence_task','" . implode(',', $sequenceSyncData['task']) . "',
                                '$.sequence_media','" . implode(',', $sequenceSyncData['media']) . "') WHERE `id` = {$relatedShot['entity_id']}");
                        // 触发实体关联检查队列
                        Client::send('entity_relation_changed', build_queue_data_with_xu(['id' => $relatedShot['entity_id']]));
                    }
                }
                // 更新动捕序列的关联关系
                if (!empty($entity['storyboard_motion_sequence'])) {
                    try {
                        $this->updateMotionSequenceRelation($entity['storyboard_motion_sequence']);
                    } catch (Throwable $e) {
                        trace(format_exception_info($e), 'ERR');
                    }
                }
                $sourceAssets = explode(',', $entity[$sourceAssetField] ?? '');
                $sourceLevels = explode(',', $entity[$sourceLevelField] ?? '');
                $sourceTasks = explode(',', $entity[$sourceTaskField] ?? '');
                break;
            default:
                return [];
        }
        /**
         * 主要同步关联的资产和关卡
         */
        $commonService = CommonService::instance('entity');
        foreach ($relatedEntities as $relatedEntity) {
            $moduleCode = Module::$moduleDictData['module_index_by_id'][$relatedEntity['module_id']]['code'] ?? null;
            // 不追加更新 做替换更新
            $newAssets = $sourceAssets;
            $newLevels = $sourceLevels;
            $newTasks = $sourceTasks;
            $entityChanged[] = $relatedEntity['id'];
            $updateData = [
                'id' => $relatedEntity['id'],
                "{$moduleCode}_asset" => implode(',', $newAssets),
                "{$moduleCode}_level" => implode(',', $newLevels),
                "{$moduleCode}_task" => implode(',', $newTasks),
                "{$moduleCode}_media" => implode(',', $sourceMedias),
            ];
            try {
                request()->getModuleCode($moduleCode);
                $res[] = $commonService->setCurrentModuleCode($moduleCode)->update($updateData, $moduleCode, false);
                // 触发实体关联检查队列
                Client::send('entity_relation_changed', build_queue_data_with_xu(['id' => $relatedEntity['id']]));
                //更新关联关系表
                EntityRelationshipService::getInstance()->saveEntityRelationshipList($relatedEntity['id'], array_merge($newAssets, $newLevels));
            } catch (Throwable $e) {
                $res[] = [
                    'code' => $e->getCode(),
                    'message' => $e->getMessage(),
                    'request_data' => $updateData,
                ];
                $currentModuleCode = !empty(request()) ? request()->getModuleCode() : "missing";
                trace(format_exception_info($e) . $currentModuleCode . var_export($updateData, true), 'ERR');
            }
        }
        if (count($entityChanged)) {
            /**
             * 关联关系发生变化 那么检查牵扯的订单是否依赖发生变化
             */
            $orderIdList = model(OrderModel::class)
                ->join('order_task_list otl ON otl.order_id = `order`.id')
                ->where([
                    'otl.entity_id' => ['IN', $entityChanged],
                    '`order`.status' => 'inprogress',
                ])->group('`order`.id')->field('`order`.id')->select();
            $orderIdList = array_column($orderIdList, 'id', 'id');
            foreach ($orderIdList as $orderId) {
                Client::send('generate_order_task_file_list', build_queue_data_with_xu(['order_id' => $orderId, 'user_id' => 0]));
            }
        }
        return $res;
    }

    /**
     * 更新动捕序列的关联关系
     * @param $storyboardMotionSequenceId
     * @throws Exception
     */
    private function updateMotionSequenceRelation($storyboardMotionSequenceId)
    {
        // 关联的动捕序列 同步关联关系
        $motionSequence = model(EntityModel::class)->find($storyboardMotionSequenceId);
        if (empty($motionSequence)) {
            return;
        }
        $motionSequence['json'] = json_decode($motionSequence['json'], true);
        $motionSequence['json']['sequence_storyboard'] = explode(',', $motionSequence['json']['sequence_storyboard'] ?? '');
        if (empty($motionSequence['json']['sequence_storyboard'])) {
            return;
        }
        $motionSequence['asset'] = explode(',', $motionSequence['json']['sequence_asset'] ?? '');
        $motionSequence['level'] = explode(',', $motionSequence['json']['sequence_level'] ?? '');
        $relationFields = "json->>'$.storyboard_level' as level,json->>'$.storyboard_asset' as asset";
        $storyboardList = model(EntityModel::class)->where(['id' => ['IN', implode(',', $motionSequence['json']['sequence_storyboard'])]])->field($relationFields)->select();
        $syncFields = ['level', 'asset'];
        $sequenceSyncData = ['level' => [], 'asset' => []];
        foreach ($storyboardList as $storyboard) {
            foreach ($syncFields as $field) {
                $storyboard[$field] = explode(',', $storyboard[$field]);
                foreach ($storyboard[$field] as $item) {
                    $item = intval($item);
                    if ($item > 0 && !in_array($item, $sequenceSyncData[$field])) {
                        $sequenceSyncData[$field][] = $item;
                    }
                }
            }
        }
        $updated = [];
        foreach ($syncFields as $field) {
            sort($motionSequence[$field]);
            sort($sequenceSyncData[$field]);
            if ($motionSequence[$field] !== $sequenceSyncData[$field]) {
                $updated['sequence_' . $field] = implode(',', $sequenceSyncData[$field]);
            }
        }
        if (empty($updated)) {
            return;
        }
        $updated = build_update_json('json', $updated);
        model(EntityModel::class)->execute(sprintf("UPDATE entity SET %s where id = {$storyboardMotionSequenceId}", $updated));
    }


    /**
     * 灯光关联
     * @param $data
     * @param string $moduleCode
     * @param $beRelatedEntity
     * @return array
     */
    public function handleLightingRelation($data, string $moduleCode, $beRelatedEntity)
    {
        //更新的实体ID
        $entityId = $beRelatedEntity['id'];

        $updateJsonSql = '';
        // 关联角色  ｜｜  场景
        if (isset($data['related_asset'])) {
            $nameStr = $this->getEntityNamesByIds($data['related_asset']);
            $updateJsonSql .= ",'$.level_relate_asset','{$nameStr}'";
        }

        $updateJsonSql = ltrim($updateJsonSql, ',');
        if (!empty($updateJsonSql)) {
            model(EntityModel::class)->execute("UPDATE entity set json = json_set(IFNULL(json,'{}'),{$updateJsonSql}) where id = {$entityId}");
        }

        return [$entityId];
    }

    /**
     * 获取实体名称
     * @param array $ids 实体ID数组
     * @return string
     */
    private function getEntityNamesByIds(array $ids)
    {
        $list = [];
        if ($ids) {
            $list = model(EntityModel::class)->where(['id' => ['IN', $ids]])->field('name')->column('name');
        }
        return implode(',', $list);
    }

}
